#include "napi/native_api.h"
#include <hilog/log.h>
#include <multimedia/player_framework/native_avscreen_capture.h>
#include <multimedia/player_framework/native_avscreen_capture_base.h>
#include <multimedia/player_framework/native_avscreen_capture_errors.h>
#include <multimedia/player_framework/native_avcodec_audiocodec.h>
#include <multimedia/native_audio_channel_layout.h>
#include <multimedia/player_framework/native_avcodec_videoencoder.h>
#include <multimedia/player_framework/native_avcapability.h>
#include <multimedia/player_framework/native_avcodec_base.h>
#include <multimedia/player_framework/native_avformat.h>
#include <multimedia/player_framework/native_avbuffer.h>
#include <fcntl.h>
#include <mutex>
#include <native_buffer/native_buffer.h>
#include <queue>
#include "string"
#include "unistd.h"
#include <thread>
#include <cstdio>
#include <map>
#include <vector>
#include "iostream"
#include "fstream"

bool isRunning = false;
OH_AVScreenCapture *capture;
std::string outputFilePath = "/data/app/el2/100/base/com.example.capture/haps/entry/files/screen_record.mp4";

// 初始化队列
class AEncBufferSignal {
public:
    std::mutex inMutex_;
    std::mutex outMutex_;
    std::mutex startMutex_;
    std::condition_variable inCond_;
    std::condition_variable outCond_;
    std::condition_variable startCond_;
    std::queue<uint32_t> inQueue_;
    std::queue<uint32_t> outQueue_;
    std::queue<OH_AVBuffer *> inBufferQueue_;
    std::queue<OH_AVBuffer *> outBufferQueue_;
};
AEncBufferSignal *signal_ = new AEncBufferSignal();

// 文件写入相关
std::ofstream outputFile;
std::mutex fileMutex;

// 正确定义日志领域和标签
#undef LOG_DOMAIN
#undef LOG_TAG
#define LOG_DOMAIN 0x3200 // 替换为你的业务领域标识
#define LOG_TAG "CPP_TAG" // 替换为你的模块标识

// 定义不同级别的日志宏，自动添加文件名和行号
#define LOG_ERROR(fmt, ...) OH_LOG_ERROR(LOG_APP, "[%{public}s:%{public}d] " fmt, __FILE__, __LINE__, ##__VA_ARGS__);
#define LOG_INFO(fmt, ...) OH_LOG_INFO(LOG_APP, "[%{public}s:%{public}d] " fmt, __FILE__, __LINE__, ##__VA_ARGS__);
#define LOG_DEBUG(fmt, ...) OH_LOG_DEBUG(LOG_APP, "[%{public}s:%{public}d] " fmt, __FILE__, __LINE__, ##__VA_ARGS__);
#define LOG_WARN(fmt, ...) OH_LOG_WARN(LOG_APP, "[%{public}s:%{public}d] " fmt, __FILE__, __LINE__, ##__VA_ARGS__);

static void OnError(OH_AVScreenCapture *capture, int32_t errorCode, void *userData) {
    LOG_ERROR("OnError occurred, errorCode: %{public}d", errorCode);
    (void)capture;
    (void)userData;

    // 发生错误时停止录屏
    if (isRunning) {
        OH_AVScreenCapture_StopScreenCapture(capture);
        isRunning = false;

        std::lock_guard<std::mutex> lock(fileMutex);
        if (outputFile.is_open()) {
            outputFile.close();
        }
    }
};

static void OnStateChange(struct OH_AVScreenCapture *capture, OH_AVScreenCaptureStateCode stateCode, void *userData) {
    LOG_INFO("OnStateChange: %{public}d", stateCode);

    switch (stateCode) {
    case OH_SCREEN_CAPTURE_STATE_STARTED:
        LOG_INFO("Screen capture started successfully");
        isRunning = true;
        break;
    case OH_SCREEN_CAPTURE_STATE_STOPPED_BY_CALL:
        LOG_INFO("Screen capture stopped by call");
        isRunning = false;
        break;
    case OH_SCREEN_CAPTURE_STATE_INTERRUPTED_BY_OTHER:
        LOG_INFO("Screen capture interrupted by other");
        isRunning = false;
        break;
    default:
        break;
    }
    (void)userData;
};

static void OnBufferAvailable(OH_AVScreenCapture *capture, OH_AVBuffer *buffer, OH_AVScreenCaptureBufferType bufferType,
                              int64_t timestamp, void *userData) {
    // 对于文件输出模式，数据会自动写入文件，这里主要做状态监控
    if (bufferType == OH_SCREEN_CAPTURE_BUFFERTYPE_VIDEO) {
        LOG_DEBUG("Video buffer received, timestamp: %{public}lld", timestamp);
    } else if (bufferType == OH_SCREEN_CAPTURE_BUFFERTYPE_AUDIO_INNER) {
        LOG_DEBUG("Inner audio buffer received, timestamp: %{public}lld", timestamp);
    } else if (bufferType == OH_SCREEN_CAPTURE_BUFFERTYPE_AUDIO_MIC) {
        LOG_DEBUG("Mic audio buffer received, timestamp: %{public}lld", timestamp);
    }

    // 释放buffer
    OH_AVBuffer_Destroy(buffer);
};

int startRecording() {
    if (isRunning) {
        LOG_WARN("Recording is already running");
        return 1;
    }
    // 1. 创建AVScreenCapture实例
    capture = OH_AVScreenCapture_Create();
    if (capture == nullptr) {
        LOG_ERROR("Failed to create AVScreenCapture instance");
        return -1;
    }

    // 2. 配置录屏参数
    OH_AVScreenCapture_SetCanvasRotation(capture, true);

    // 3. 配置音频过滤器（可选）
    OH_AVScreenCapture_ContentFilter *contentFilter = OH_AVScreenCapture_CreateContentFilter();
    if (contentFilter != nullptr) {
        OH_AVScreenCapture_ContentFilter_AddAudioContent(contentFilter, OH_SCREEN_CAPTURE_NOTIFICATION_AUDIO);
        OH_AVScreenCapture_ExcludeContent(capture, contentFilter);
        OH_AVScreenCapture_ReleaseContentFilter(contentFilter);
    }

    // 4. 配置录屏参数
    OH_AudioCaptureInfo miccapinfo = {.audioSampleRate = 48000, .audioChannels = 2, .audioSource = OH_MIC};
    OH_AudioCaptureInfo innerCapInfo = {.audioSampleRate = 48000, .audioChannels = 2, .audioSource = OH_ALL_PLAYBACK};
    OH_AudioEncInfo audioEncInfo = {.audioBitrate = 128000, .audioCodecformat = OH_AAC_LC};
    OH_VideoCaptureInfo videoCapInfo = {
        .videoFrameWidth = 720, .videoFrameHeight = 1280, .videoSource = OH_VIDEO_SOURCE_SURFACE_RGBA};
    OH_VideoEncInfo videoEncInfo = {.videoCodec = OH_H264, .videoBitrate = 2000000, .videoFrameRate = 30};
    OH_AudioInfo audioInfo = {.micCapInfo = miccapinfo, .innerCapInfo = innerCapInfo, .audioEncInfo = audioEncInfo};
    OH_VideoInfo videoInfo = {.videoCapInfo = videoCapInfo, .videoEncInfo = videoEncInfo};
    
    // 5. 配置输出文件信息 - 使用字符数组
    char filePath[256]; // 确保大小足够
    strncpy(filePath, outputFilePath.c_str(), sizeof(filePath) - 1);
    filePath[sizeof(filePath) - 1] = '\0'; // 确保以null结尾
    LOG_INFO("保存的路径filePath: %{public}s", filePath);
    OH_RecorderInfo recorderInfo = {
//        .url = "/data/storage/el2/base/media/screen_record.mp4", // 输出文件路径
        .url = filePath, // 输出文件路径
        .fileFormat = OH_ContainerFormatType::CFT_MPEG_4         // 容器格式为MP4
    };

    OH_AVScreenCaptureConfig config = {.captureMode = OH_CAPTURE_HOME_SCREEN, // 录制主屏幕
                                       .dataType = OH_CAPTURE_FILE,           // 输出为文件
                                       .audioInfo = audioInfo,
                                       .videoInfo = videoInfo,
                                       .recorderInfo = recorderInfo};

    // 6. 设置回调
    OH_AVScreenCapture_SetErrorCallback(capture, OnError, signal_);
    OH_AVScreenCapture_SetStateCallback(capture, OnStateChange, signal_);
    OH_AVScreenCapture_SetDataCallback(capture, OnBufferAvailable, signal_);

    // 7. 初始化录屏
    int32_t ret = OH_AVScreenCapture_Init(capture, config);
    if (ret != AV_SCREEN_CAPTURE_ERR_OK) {
        LOG_ERROR("Failed to initialize screen capture: %{public}d", ret);
        OH_AVScreenCapture_Release(capture);
        capture = nullptr;
        return ret;
    }

    // 8. 开始录屏
    ret = OH_AVScreenCapture_StartScreenCapture(capture);
    if (ret != AV_SCREEN_CAPTURE_ERR_OK) {
        LOG_ERROR("Failed to start screen capture: %{public}d", ret);
        OH_AVScreenCapture_Release(capture);
        capture = nullptr;
        return ret;
    }

    LOG_INFO("Screen recording started, output file: %{public}s", outputFilePath.c_str());
    return 0;
}

int stopRecording() {
    if (!isRunning || capture == nullptr) {
        LOG_WARN("Recording is not running");
        return 0;
    }

    int32_t ret = OH_AVScreenCapture_StopScreenCapture(capture);
    if (ret != AV_SCREEN_CAPTURE_ERR_OK) {
        LOG_ERROR("Failed to stop screen capture: %{public}d", ret);
    } else {
        LOG_INFO("Screen recording stopped successfully");
    }

    OH_AVScreenCapture_Release(capture);
    capture = nullptr;
    isRunning = false;
    return ret;
}

// NAPI 接口函数
static napi_value StartRecording(napi_env env, napi_callback_info info) {
    int ret = startRecording();

    napi_value result;
    napi_create_int32(env, ret, &result);
    return result;
}

static napi_value StopRecording(napi_env env, napi_callback_info info) {
    int ret = stopRecording();

    napi_value result;
    napi_create_int32(env, ret, &result);
    return result;
}

static napi_value IsRecording(napi_env env, napi_callback_info info) {
    napi_value result;
    napi_get_boolean(env, isRunning, &result);
    return result;
}

static napi_value SetOutputPath(napi_env env, napi_callback_info info) {
    size_t argc = 1;
    napi_value args[1];
    napi_get_cb_info(env, info, &argc, args, nullptr, nullptr);

    if (argc < 1) {
        napi_throw_error(env, nullptr, "Wrong number of arguments");
        return nullptr;
    }

    size_t str_len;
    napi_get_value_string_utf8(env, args[0], nullptr, 0, &str_len);
    char *filePath = new char[str_len + 1];
    napi_get_value_string_utf8(env, args[0], filePath, str_len + 1, &str_len);

    outputFilePath = std::string(filePath);
    LOG_INFO("设置了保存路径：%{public}s", outputFilePath.c_str())
    delete[] filePath;

    napi_value result;
    napi_create_int32(env, 0, &result);
    return result;
}

EXTERN_C_START
static napi_value Init(napi_env env, napi_value exports) {
    napi_property_descriptor desc[] = {
        {"startRecording", nullptr, StartRecording, nullptr, nullptr, nullptr, napi_default, nullptr},
        {"stopRecording", nullptr, StopRecording, nullptr, nullptr, nullptr, napi_default, nullptr},
        {"isRecording", nullptr, IsRecording, nullptr, nullptr, nullptr, napi_default, nullptr},
        {"setOutputPath", nullptr, SetOutputPath, nullptr, nullptr, nullptr, napi_default, nullptr}};
    napi_define_properties(env, exports, sizeof(desc) / sizeof(desc[0]), desc);
    return exports;
}
EXTERN_C_END

static napi_module demoModule = {
    .nm_version = 1,
    .nm_flags = 0,
    .nm_filename = nullptr,
    .nm_register_func = Init,
    .nm_modname = "capture",
    .nm_priv = ((void *)0),
    .reserved = {0},
};

extern "C" __attribute__((constructor)) void RegisterCaptureModule(void) { napi_module_register(&demoModule); }